<?php

    //Database singleton - extends MySQLI library.
    class DBConnection extends mysqli {
        private static $instance;
        
        private function __construct() {
            $conf = Config::inst();
            parent::__construct($conf->DBHost,$conf->DBUser,$conf->DBPass,$conf->DBName);
        }

        /**
         * Return a single instance of this object. If we don't currently have one,
         * create a singleton adn sreturn it.
         * @return DBConnection
         */
        public static function inst() {
            if(!isset(self::$instance)) {
                $c = __CLASS__;
                self::$instance = new $c;
            }
            return self::$instance;
        }
        
        /**
         * Executes a stored procedure query. (Technically capable of any query,
         * but this has additional logic to ensure that sprocs return all results.
         * @param string $procedure The procedure in the database to execute
         * @param array $params Any additional parameters (in order) to be passed to the routine
         * @param array $returnData Reference to variable to store results;
         * @return int return result of procedure;
         */
        public function executeStoredProcedure($procedure, $params, &$returnData) {
            $returnVal = 0;
            $realParams = Array('@r'); //Set first parameter to always be the return value;
            
            if (is_array($params)) {
                foreach ($params as $p) {
                    if (is_string($p) && (strtolower($p) !== 'null' &&
                                          strtolower($p) != 'true' &&
                                          strtolower($p) != 'false')) {
                        $p = '\'' . $this->escape_string($p) . '\'';
                        //echo $p;
                    }
                    if (!isset($p) || is_null($p) || strtolower($p) === 'null') {
                        $p = 'NULL';
                    }

                    if (is_string($p) && 
                       (strtolower($p) == 'true' ||
                        strtolower($p) == 'false'))
                    {
                        $p = strtolower($p) == 'true' ? true : false;
                    }
                    
                    if (is_bool($p)) {
                        $p = (int)$p;
                    }
                    $realParams[] = $p;
                }
            } 
            else {
                if(is_string($params) && strtolower($params) !== 'null') {
                    $params = '\'' . $this->escape_string($params) . '\'';
                }
                $realparams[] = $params;
            } //Go through the parameters listed, escape any strings,
            //print_r($realParams);
            $realParams = implode(',', $realParams); //Create the final parameter string;
            //echo ($realParams);
            $realQueryString = ("CALL $procedure ($realParams); SELECT @r AS _returnVal;");
            if ($this->multi_query($realQueryString)) { //If succesful go through results and fetch to ReturnData;
                $returnData = Array();
                do {
                    if ($r = $this->use_result()) {
                        while ($data = $r->fetch_assoc()) {
                            if (isset($data['_returnVal'])) {
                                $returnVal = $data['_returnVal'];     //If this record is the return value of the stored procedure
                                                                    //store into ReturnVal and ignore the result set;
                            }
                            else {
                                $returnData[] = $data;                //Store the result;
                            }
                        }
                        if ($r instanceof mysqli_result) {
                            $r->free();                                //And free the result
                        }
                    }
                } while($this->next_result()); //Fetch results as long as there are some to select (stored procedures)
            }
            else {
                throw new CriticalException('Database error. MySQL reports: ' . $this->error); //We broke the database, good job
            }

            return $returnVal;
        }
    }
?>